﻿using BJoin.Application.WebApi.Helper;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Formatters;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace BJoin.Application.WebApi.Extensions
{
    public static class HttpRequestExtensions
    {

        /// <summary>
        /// Retrieve the raw body as a string from the Request.Body stream
        /// </summary>
        /// <param name="request">Request instance to apply to</param>
        /// <param name="encoding">Optional - Encoding, defaults to UTF8</param>
        /// <returns></returns>
        public static async Task<string> GetRawBodyStringAsync(this HttpRequest request, Encoding encoding = null)
        {
            if (encoding == null)
                encoding = Encoding.UTF8;

            using (StreamReader reader = new StreamReader(request.Body, encoding))
                return await reader.ReadToEndAsync();
        }

        /// <summary>
        /// Retrieves the raw body as a byte array from the Request.Body stream
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static async Task<byte[]> GetRawBodyBytesAsync(this HttpRequest request)
        {
            using (var ms = new MemoryStream(2048))
            {
                await request.Body.CopyToAsync(ms);
                return ms.ToArray();
            }
        }
        public static async Task<string> ReadSteamAsync(this HttpRequest request)
        {
            string bodyString = null;
            //if (request.ContentLength <= 0) return null;

            //if (!request.Body.CanSeek)
            //{
            //    EnableRewind(request);
            //}
            //
            if (request.Body.CanSeek)
            {
                var position = request.Body.Position;
                request.Body.Seek(0, SeekOrigin.Begin);
                var streamReader = new StreamReader(request.Body);
                request.HttpContext.Response.RegisterForDispose(streamReader);
                bodyString = await streamReader.ReadToEndAsync();
                request.Body.Seek(position, SeekOrigin.Begin);
            }
            return bodyString;
        }

        public static HttpRequest EnableRewind(HttpRequest request)
        {
            request.EnableBuffering();
            return request;
        }

        public static Encoding GetRequestEncoding(this HttpRequest request)
        {
            var requestContentType = request.ContentType;
            var requestMediaType = requestContentType == null ? default(MediaType) : new MediaType(requestContentType);
            var requestEncoding = requestMediaType.Encoding;
            if (requestEncoding == null)
            {
                requestEncoding = Encoding.UTF8;
            }
            return requestEncoding;
        }

        public static HttpResponse EnableRewind(this HttpResponse response)
        {
            if (response == null)
            {
                throw new ArgumentNullException(nameof(response));
            }
            var body = response.Body;
            if (!response.Body.CanRead || !response.Body.CanSeek)
            {
                var responseBodyStream = new WriteSyncMemoryStream(body);
                response.Body = responseBodyStream;
                response.HttpContext.Response.RegisterForDispose(responseBodyStream);
            }
            return response;
        }

        public static async Task<string> ReadSteamAsync(this HttpResponse response)
        {
            string bodyString = null;
            if (response.Body.CanSeek)
            {
                var position = response.Body.Position;
                response.Body.Seek(0, SeekOrigin.Begin);
                var streamReader = new StreamReader(response.Body);
                response.RegisterForDispose(streamReader);
                bodyString = await streamReader.ReadToEndAsync();
                response.Body.Seek(position, SeekOrigin.Begin);
            }
            return bodyString;
        }
    }
}
